import React, {
  useState,
  useMemo,
  useEffect,
  useCallback,
  useRef,
  HTMLAttributes,
  memo
} from 'react';
import './todo.css'

interface IState {
  id: any,
  text: string,
  complete: boolean
}

interface IProps {
  current?: any,
  addTodo?: any,
  value?: string,
}

type subType = (e: React.FormEvent<HTMLFormElement>) => void

let idSeq: any = new Date();

const Control = memo(function Control(props: IProps) {
  const { addTodo } = props;
  const inputRef: React.MutableRefObject<any> = useRef(null)
  const onSubmit: subType = (e) => { // 没有向任何子组件传递，所以不需要用useCallback包裹
    e.persist()
    e.preventDefault();
    const newText = inputRef.current.value.trim()
    if (newText.length === 0) {
      return;
    }
    addTodo({
      id: ++idSeq,
      text: newText,
      complete: false
    })
    inputRef.current.value = ''
  }

  return <div className="control">
    <h1>todos</h1>
    <form onSubmit={onSubmit}>
      <input
        ref={inputRef}
        type="text"
        className="new-todo"
        placeholder="What needs to be done?"
      />
    </form>
  </div>
})

// 列表的li组件
const TodoItem = memo(function TodoItem(props: any) {
  let {
    todo: {
      id, text, complete
    },
    toggleTodo,
    removeTodo
  } = props;

  const onChange = () => {
    toggleTodo(id)
  }

  const onRemove = () => {
    removeTodo(id)
  }

  return <li className="todo-item">
    <input
      type="checkbox"
      onChange={onChange}
      checked={complete}
    />
    <label className={complete ? "complete" : ""}>{text}</label>
    <button onClick={onRemove}>&#xd7;</button>
  </li>
})

// 列表组件
const Todos = memo(function Todos(props: any) {
  let { todos, toggleTodo, removeTodo } = props
  return (
    <ul>
      {
        todos.map((todo: IState) => {
          return (
            <TodoItem
              key={todo.id}
              todo={todo}
              toggleTodo={toggleTodo}
              removeTodo={removeTodo}
            />
          )
        })
      }
    </ul>
  )
})

const TodoList = memo(function TodoList() {
  let [todos, setTodos] = useState([]);

  // useMemo: --> 返回

  const addTodo = useCallback((todo: any) => {
    (setTodos as any)((todos: any) => [...todos, todo])
  }, [])

  const removeTodo = useCallback((id) => {
    setTodos((todos: any) => todos.filter((todo: any) => {
      return todo.id !== id
    }))
  }, [])

  const toggleTodo = useCallback((id) => {
    setTodos((todos: any) => todos.map((todo: any) => {
      return todo.id === id ?
        {
          ...todo,
          complete: !todo.complete
        } : todo;
    }))
  }, [])

  useEffect(() => {
    // 
    const todos = (JSON as any).parse(localStorage.getItem('LS_KEY')) || []
    setTodos(todos)
  }, [])

  useEffect(() => {
    localStorage.setItem('LS_KEY', JSON.stringify(todos))
  }, [todos])


  return <div className="todo-list">
    <Control addTodo={addTodo} />
    <Todos
      removeTodo={removeTodo}
      toggleTodo={toggleTodo}
      todos={todos}
    />
  </div>
})

export default TodoList;


